home *** CD-ROM | disk | FTP | other *** search
- /*
- * Send / receive TCP or UDP echos in any of a number of bizzare ways.
- *
- * Joel P. Bion, March 1990
- * Copyright (c) 1990 cisco Systems. All rights reserved.
- *
- * This "tuecho" program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Prompts as:
- * Host: -- host to send echos to -- can be name or a.b.c.d --
- * Enter protocol (0 = UDP, 1 = TCP) [0]: -- UDP or TCP
- * Size of data portion (bytes) [100]: -- bytes in data, excluding headers --
- * Number of bursts [5]: -- number of bursts of packets to send --
- * Packets per burst [1]: -- packets per burst, all sent AT ONCE --
- * Timeout (seconds) [2]: -- how long to wait for data
- * Pause interval (seconds) [0]: -- Pause interval between bursts of frames
- * Type of pattern (specify = 0, increment = 1) [1]:
- * -- if 0 specified, allow you to specify a 16bit pattern as four
- * -- hex digits (see below). If 1, will create a "incrementing",
- * -- cycling pattern from 0x0000 -> 0xffff ->.
- * Enter pattern (hex value) [abcd]: -- if "0" specified above
- */
- #include <signal.h>
- #include <sys/types.h>
- #include <sys/time.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <netdb.h>
- #include <stdio.h>
- #include <arpa/inet.h>
-
- extern void printf(), fflush(), exit(), bzero(), perror(), strcpy(),
- setbuf(), sscanf(), bcopy(), close(), fprintf();
- extern int write(), read(), select(), atoi(), socket(), connect();
-
- /* Maximum packet size (integer) */
- #define MAXBUF (2000)
- #define MAXBYTES (MAXBUF * 4)
-
- /* Special patterns... */
- #define SPECIAL_NONE (0)
- #define SPECIAL_COUNTER (SPECIAL_NONE + 1)
- #define SPECIAL_MAX (SPECIAL_COUNTER)
-
- /* Protocols */
- #define PROTO_UDP (0)
- #define PROTO_TCP (PROTO_UDP + 1)
- #define PROTO_MAX (PROTO_TCP)
-
- /* Global, because interrupt routine references them */
- int
- lost, /* Packets whose echos are not received */
- good, /* We received a good reply */
- corrupted, /* We received a bad reply */
- sentout, /* How many we sent out */
- outc; /* How many chars out */
-
-
- /* Guarantee CRs at random times */
- void cprint(c)
- char c;
- {
- printf("%c", c);
- if (++outc == 70) {
- printf("\n");
- outc = 0;
- }
- fflush(stdout);
- }
-
- void cprintcr()
- {
- if (outc != 0)
- printf("\n");
- }
-
- unsigned getint(prompt, defa, fc)
- char *prompt;
- unsigned defa;
- char fc;
- {
- char s[1000];
- unsigned u;
-
- if (fc == 'x')
- printf("%s [%x]: ", prompt, defa);
- else
- printf("%s [%d]: ", prompt, defa);
- fgets(s, 999, stdin);
- if ((s[0] == '\0') || (s[0] == '\n'))
- return(defa);
- else {
- if (fc == 'x')
- sscanf(s,"%x", &u);
- else
- sscanf(s,"%d", &u);
- return(u);
- }
- }
-
-
-
- void outhere()
- {
- cprintcr();
- printf("\nAt end, sent out = %d, good = %d, lost = %d, corrupted = %d.\n",
- sentout, good, lost, corrupted);
- }
-
- void outhere_exit()
- {
- outhere();
- exit(0);
- }
-
- void usage_exit()
- {
- printf("usage: tuecho\n");
- printf(" with no parameters will prompt you for information, or another form:\n");
- printf("\n tuecho host proto size nbursts ppburst timeout pauseint ptype\n");
- printf(" [pattern] (on same command line as above)\n");
- printf("\n");
- printf(" Where:\n");
- printf(" host: host to receive your echos. (can be name or a.b.c.d form)\n");
- printf(" proto: 0 for UDP, 1 for TCP\n");
- printf(" size: size of echo packet, excluding headers\n");
- printf(" nbursts: total number of \"bursts\" of echo packets to send\n");
- printf(" ppburst: how many echo packets should be in each burst\n");
- printf(" timeout: how many seconds to wait for the reply (allow more time for bursts)\n");
- printf(" pauseint: Pause interval, in seconds, between bursts\n");
- printf(" ptype: 0 to allow you to specify a hex pattern as the final \"pattern\" parameter\n");
- printf(" 1 for \"increasing cyclic\" 16-bit pattern going from 0x0000 to 0xffff\n");
- printf(" and back again, until each echo packet is filled\n");
- printf(" pattern: four character hex pattern (no leading 0x), if ptype = 1, to insert repeatedly\n");
- printf(" in the echo packets\n");
- exit(0);
- }
-
- void sendrecvechos(sock, ptype, pattern, bufsize, bursts, burstsize, timeout,
- pause_int)
- int sock; /* Socket to send / receive from */
- int ptype; /* Pattern type (normal, or a special) */
- int pattern; /* Pattern (if normal) */
- int bufsize; /* Buffer size to send */
- int bursts; /* Number of bursts */
- int burstsize; /* Size of bursts */
- struct timeval timeout; /* Timeout */
- int pause_int; /* Pause interval */
- {
- int i, j, k, ok, readin;
- int nb;
- unsigned int bufo[MAXBUF]; /* Packet to send out */
- unsigned int bufi[MAXBUF]; /* Packet to accept */
- fd_set readmask; /* For "select" call */
-
- /* Set up select mask */
- FD_ZERO(&readmask);
- FD_SET(sock, &readmask);
- /* Set up the pattern. Check for specials... */
- switch (ptype) {
- case SPECIAL_COUNTER:
- for (i = 0; i < (bufsize / 4); i++)
- bufo[i] = i;
- break;
- case SPECIAL_NONE:
- default:
- for (i = 0; i < (bufsize / 4); i++)
- bufo[i] = pattern;
- break;
- }
- for (i = 0; (i < bursts); i++) {
- if (pause_int)
- sleep(pause_int);
- if (ptype == SPECIAL_COUNTER)
- bufo[0] = i;
- for (j = 0; j < burstsize; j++) {
- if (write(sock, (char *) bufo, bufsize) < 0) {
- perror("writing on datagram socket.");
- outhere();
- exit(1);
- }
- sentout++;
- }
- for (j = 0; j < burstsize; j++) {
- nb = select(FD_SETSIZE, &readmask, (fd_set *) 0,
- (fd_set *) 0, &timeout);
- if (nb <= 0) {
- lost++;
- cprint('.');
- FD_SET(sock, &readmask);
- continue;
- }
- if (FD_ISSET(sock, &readmask)) {
- bzero((char *) bufi, bufsize);
- if ((readin = read(sock, (char *) bufi, bufsize)) < 0) {
- perror("Reading on datagram socket.");
- outhere();
- exit(1);
- } else {
- ok = 1;
- for (k = 0; ((k < (bufsize / 4)) && (ok)); k++)
- ok = (bufo[k] == bufi[k]);
- if (!(ok)) {
- corrupted++;
- cprint('*');
- continue;
- } else {
- good++;
- cprint('!');
- continue;
- }
- }
- }
- }
- }
- outhere();
- }
-
- void printinfo(ptype, pattern, bufsize, bursts, burstsize, timeout, server,
- proto, pause_int)
- int ptype; /* Pattern type (normal, or a special) */
- int pattern; /* Pattern (if normal) */
- int bufsize; /* Buffer size to send */
- int bursts; /* Number of bursts */
- int burstsize; /* Size of bursts */
- struct timeval timeout; /* Timeout */
- struct sockaddr_in server; /* Remote server IP address */
- int proto; /* Protocol */
- int pause_int;
-
- {
- printf("\nSending %d bursts of %d %s packets, data portions being %d bytes,\n",
- bursts, burstsize, ((proto == PROTO_TCP) ? ("TCP") : ("UDP")),
- bufsize);
- printf("with a timeout of %d seconds,\nthe pattern being ",
- timeout.tv_sec);
- switch (ptype) {
- case SPECIAL_COUNTER:
- printf("an incrementing value in the packet");
- break;
- case SPECIAL_NONE:
- default:
- printf("0x%x in each four bytes", pattern);
- break;
- }
- printf("\n");
- printf("Pause interval: %d seconds\n", pause_int);
- printf("Sending to IP address %u.%u.%u.%u...\n",
- (unsigned) server.sin_addr.S_un.S_un_b.s_b1,
- (unsigned) server.sin_addr.S_un.S_un_b.s_b2,
- (unsigned)server.sin_addr.S_un.S_un_b.s_b3,
- (unsigned) server.sin_addr.S_un.S_un_b.s_b4);
- }
-
- void askinfo(argc, argv, hostname, proto,
- bufsize, bursts, burstsize, timeout, ptype, pattern, pause_int)
- int argc;
- char **argv, *hostname;
- int *proto, *bufsize, *bursts, *burstsize;
- struct timeval *timeout;
- int *ptype;
- unsigned *pattern;
- int *pause_int;
- {
- if ((argc > 9) || ((argc == 2) && (argv[1][0] == '-') &&
- (argv[1][1] == 'h')))
- usage_exit();
-
- if (argc > 1)
- strcpy(hostname, argv[1]);
- else {
- printf("Host: ");
- gets(hostname);
- }
- *proto = ((argc > 2) ? (atoi(argv[2])) :
- (int) getint("Enter protocol (0 = UDP, 1 = TCP)", 0, 'd'));
- *bufsize = ((argc > 3) ? (atoi(argv[3])) :
- (int) getint("Size of data portion (bytes)", 100, 'd'));
- *bursts = ((argc > 4) ? (atoi(argv[4])) :
- (int) getint("Number of bursts", 5, 'd'));
- *burstsize = ((argc > 5) ? (atoi(argv[5])) :
- (int) getint("Packets per burst", 1, 'd'));
- timeout->tv_sec = ((argc > 6) ? (atoi(argv[6])) :
- (int) getint("Timeout (seconds)", 2, 'd'));
- *pause_int = ((argc > 7) ? (atoi(argv[7])) :
- (int) getint("Enter pause interval", 0, 'd'));
- *ptype = ((argc > 8) ? (atoi(argv[8])) :
- (int) getint("Type of pattern (specify = 0, increment = 1)",
- 1, 'd'));
- if (*ptype == SPECIAL_NONE)
- if (argc > 9)
- sscanf(argv[9], "%x", pattern);
- else
- *pattern = getint("Enter pattern (hex value)", 0xabcd, 'x');
- }
-
- void init()
- {
- setbuf(stdout, NULL);
- good = sentout = corrupted = lost = outc = 0;
- }
-
- void main(argc, argv)
- int argc;
- char **argv;
- {
- char hostname[1000];
- int bufsize, bursts, proto, ptype, burstsize, sock;
- struct hostent *hp, *gethostbyname();
- struct in_addr ip;
- struct sockaddr_in server;
- struct timeval timeout;
- unsigned int pattern, pause_int;
-
- askinfo(argc, argv, hostname, &proto, &bufsize, &bursts, &burstsize,
- &timeout, &ptype, &pattern, &pause_int);
- signal(SIGINT, outhere_exit);
- ip.s_addr = inet_addr(hostname);
- if (ip.s_addr == -1) {
- hp = gethostbyname(hostname);
- if (hp == NULL) {
- fprintf(stderr, "%s: %s: unknown host\n", argv[0],
- argv[1]);
- exit(1);
- }
- bcopy(hp->h_addr, &server.sin_addr, hp->h_length);
- } else
- bcopy(&ip, &server.sin_addr, sizeof(ip));
- printinfo(ptype, pattern, bufsize, bursts, burstsize, timeout, server,
- proto, pause_int);
- sock = socket(AF_INET, SOCK_DGRAM, 0);
- if (sock < 0) {
- perror("Opening stream socket.");
- exit(1);
- }
- server.sin_family = AF_INET;
- server.sin_port = htons(((struct servent *)
- getservbyname("echo",((proto == PROTO_UDP) ?
- ("udp") : ("tcp")
- )))->s_port);
- if (connect(sock, &server, sizeof(server)) < 0) {
- perror("connecting stream socket");
- exit(1);
- }
- sendrecvechos(sock, ptype, pattern, bufsize, bursts, burstsize, timeout,
- pause_int);
- close(sock);
- exit(0);
- }
-